package com.hyz.classloadertest;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;

/**
 *  classloader小结--各版本api有出入
 *  Android中classLoader一共有5种，加上本身的Classloader这个类一共是6种，其他的都直接或间接继承自ClassLoader
 *
 *  ClassLoader的直接子类有3个 BootClassLoader、URLClassLoader、BaseDexClassLoader
 *  BaseDexClassLoader又有2个子类PathClassLoader和DexClassLoader
 *  下面分别解释一下
 *  1.ClassLoader中重要的方法是loadClass(String name)
 *  2.BootClassLoader。是ClassLoader的一个内部类、是所有其他classLoader的最终parent。这个类是包内可见、所以我们没法用。
 *  3.URLClassLoader。继承自ClassLoader只能用于加载jar文件，但是由于 dalvik 不能直接识别jar，所以在 Android 中无法使用这个加载器。
 *  4.BaseDexClassLoader是重点。BaseDexClassLoader构造函数有4个参数(见博客)
 *  5.PathClassLoader。用于加载系统类和应用的类，不建议开发者使用(在art虚拟机上PathClassLoader可以加载未安装的apk的dex)但是有点问题，不使用
 *  6.DexClassLoader。DexClassLoader支持加载APK、DEX和JAR，也可以从SD卡进行加载
 *
 *  所以我们的插件化，热更新等等都是基于DexClassLoader的。一般我们都是用这个DexClassLoader来作为动态加载的加载器。
 *
 *  BaseDexClassLoader加载class流程
 *  1.BaseDexClassLoader的findClass方法种调用PathList的findClass方法
 *  2.pathList中有一个dexElements数组，里面装的是dexFile。如果不分包就只有一个Elements、也只有一个dexFile。
 *  3.类加载的时候，遍历Elements通过dexFile.去找到类。
 *
 *  CustomFix热更新框架，就是通过DexClassLoader产生一个Elements，然后与当前应用的Elements合并(放在最前端)，、
 *  然后通过反射设置到应用的PathList种。。dexElementsField.set(pathList, dexElements);
 *
 *
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("DEMO", "Context的类加载加载器:"+Context.class.getClassLoader());
        Log.i("DEMO", "ListView的类加载器:"+ListView.class.getClassLoader());
        Log.i("DEMO", "应用程序默认加载器:"+getClassLoader());
        Log.i("DEMO", "系统类加载器:"+ClassLoader.getSystemClassLoader());
        Log.i("DEMO", "系统类加载器和Context的类加载器是否相等:"+(Context.class.getClassLoader()==ClassLoader.getSystemClassLoader()));
        Log.i("DEMO", "系统类加载器和应用程序默认加载器是否相等:"+(getClassLoader()==ClassLoader.getSystemClassLoader()));

        Log.i("DEMO","打印应用程序默认加载器的委派机制:");
        ClassLoader classLoader = getClassLoader();
        while(classLoader != null){
            Log.i("DEMO", "类加载器:"+classLoader);
            classLoader = classLoader.getParent();
        }

        Log.i("DEMO","打印系统加载器的委派机制:");
        classLoader = ClassLoader.getSystemClassLoader();
        while(classLoader != null){
            Log.i("DEMO", "类加载器:"+classLoader);
            classLoader = classLoader.getParent();
        }

        Log.i("DEMO","打印BootClassLoader的委派机制:");
        classLoader = Context.class.getClassLoader();
        while(classLoader != null){
            Log.i("DEMO", "类加载器:"+classLoader);
            classLoader = classLoader.getParent();
        }

        classLoader = classLoader.getParent();
        Log.i("DEMO", "类加载器:"+classLoader);
    }
}
